﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.HomeServer.SDK.Interop.v1;

namespace Umbrella.Whs
{
    public sealed class WhsComputers
    {
        public struct ClientEntry
        {
            public string IP;
            public string Name;
            public bool IsOffline;

            public override string ToString()
            {
                var sb = new StringBuilder();

                if (!string.IsNullOrEmpty(this.Name))
                {
                    sb.Append(this.Name);
                    sb.Append(" (");
                    sb.Append(this.IP);

                    if (this.IsOffline)
                    {
                        sb.Append("; offline");
                    }

                    sb.Append(")");
                }
                else
                {
                    sb.Append(this.IP);

                    if (this.IsOffline)
                    {
                        sb.Append(" (offline)");
                    }
                }

                return sb.ToString();
            }

            public ClientEntry(string internalClient)
            {
                if (string.IsNullOrEmpty(internalClient))
                    throw new ArgumentException("null or empty", "internalClient");

                this.IP = internalClient;
                this.Name = string.Empty;

                using (var p = new System.Net.NetworkInformation.Ping())
                {
                    this.IsOffline = (p.Send(internalClient, 200).Status != System.Net.NetworkInformation.IPStatus.Success);
                }
            }

            public ClientEntry(string ip, string machineName)
            {
                if (string.IsNullOrEmpty(ip))
                    throw new ArgumentException("null or empty", "ip");

                if (string.IsNullOrEmpty(machineName))
                    throw new ArgumentException("null or empty", "machineName");

                this.IP = ip;
                this.Name = machineName;
                this.IsOffline = false;
            }

            public ClientEntry(IComputerInfo i)
            {
                if (i == null)
                    throw new ArgumentNullException("i");

                this.IP = i.IPAddress;
                this.Name = i.ComputerName;
                this.IsOffline = (i.IsOnline == 0);
            }
        }

        private static WhsComputers _instance = new WhsComputers();

        public static WhsComputers Instance
        {
            get { return _instance; }
        }

        private readonly WHSInfo _info;

        public static byte[] LookupIpByDns(string name)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentException("null or empty", "name");

            var r = System.Net.Dns.GetHostEntry(name);

            if (r.AddressList.Length <= 0)
                return null;

            return r.AddressList[0].GetAddressBytes();
        }

        public static byte[] GetHomeServerIp()
        {
            var machineName = Environment.MachineName;
            var r = System.Net.Dns.GetHostEntry(machineName);

            if (r.AddressList.Length <= 0)
                return null;

            return r.AddressList[0].GetAddressBytes();
        }

        public IList<ClientEntry> LoadComputers()
        {
            var computers = (
                                from IComputerInfo i in _info.GetClientComputerInfo()
                                where !string.IsNullOrEmpty(i.IPAddress)
                                select i
                            );

            // parse
            var ret = new List<ClientEntry>();

            foreach (var i in computers)
            {
                ret.Add(new ClientEntry(i));
            }

            // add home server
            {
                var machineName = Environment.MachineName;
                var lookup = System.Net.Dns.GetHostEntry(machineName);

                if (lookup.AddressList.Length > 0)
                {
                    var ip = lookup.AddressList[0].ToString();

                    ret.Add(new ClientEntry(ip, machineName));
                }
                else
                {
                    ret.Add(new ClientEntry(machineName));
                }
            }

            // finalize
            ret.Sort((a, b) => a.Name.CompareTo(b.Name));

            return ret.AsReadOnly();
        }

        private WhsComputers()
        {
            _info = new WHSInfoClass();

            _info.Init(Properties.Constants.ApplicationName);
        }
    }
}